MTHREAD.TXT for MicroThread V2.5 This file contains details of the various MicroThread functions and how to use them. --------------------------------------------------------------------- void MTInitialise(void); Before you can use MicroThread in your program, you will have to initialise it by calling this function. In fact, you will need to call this function every time you want to start a new multi-threading session. That is, once the function MTStartMultiThreading() returns, MicroThread has been put back into an un-initialised state, and MTInitialise() will need to be call again if you want to re-start multi-threading. --------------------------------------------------------------------- enum MTReturnCode MTStartMultiThreading(void); This function starts the MicroThread scheduler and thus multi- threading. All threads which have been created usng MTAddNewThread() will start executing concurrently. MTStartMultiThreading will return if thee is an error condition or if one of the thread executes the function MTEndMultiThreading(). When MTStartMultiThreading() returns, its return value would indicate the terminating conditions, which would be one of the following: enum MTReturnCode { NORMAL, DEADLOCKED, CTRLBREAK, NOT_INITIALISED, TOO_DEEP_CRITICAL_NEST }; NORMAL indicates a normal exit, usually as a result of calling MTEndMultiThreading(). DEADLOCKED means that the scheduler wasn't able to find a thread to dispatch, so all the active threads must be deadlocked. The scheduler can also be easily fooled by the fact that all the threads have ended and thus assume that no thread = deadlock. CTRLBREAK basically indicates that multi-threading was stopped by the user hitting Control-BREAK. NOT_INITIALISED is obvious. TOO_DEEP_CRITICAL_NEST is returned if one of the threads calls MTEnterCritical() too many times without calling MTLeaveCritical(). --------------------------------------------------------------------- int MTAddNewThread(PThreadFunc pThreadFunc, unsigned priority, unsigned sizeArg, void *pArg); This function creates and adds a new thread to the scheduler's READY queue, ready to be activated by the scheduling. Threads can only be added after MTInitialise() has been called. Threads can be added before MTStartMultThreading() or by one or more of the threads when multi-threading. The first parameter, pThreadFunc, is a pointer to the function which is to execute as a thread, and is of the type: typedef int (far *PThreadFunc) (void *pArg); The second parameter is the priority of the thread, from 1 to 5, with 1 being the lowest priority and 5 being the highest priority. The parameter sizeArg describes the size of the memory block pointed to by the next parameter *pArg, which is passed as an argument to the thread function. A copy of this block of memory is made to another area before the function returns, thus you can deallocate the original memory when the function returns. The scheduler will take care of deallocating the copy when the thread terminates. If you pass a NULL for pArg, sizeArg is ignored, and no copy will be made. There are two macros which are just variations on this funtion call: MTAddThread(pThreadFunc, priority) which are more convenient for functions which don't take parameters, and MTAddArgThread(pThreadFunc, priority, sizeArg, *pArg) which is mainly for backward compatibility with an older version of MicroThread. MTAddNewThread() returns a thread identifier which is a handle to the thread. If it returns zero, then an error has occurred and no new thread was created. --------------------------------------------------------------------- void MTKillThread(unsigned threadID); This function just kills the specified thread. Can only be used during multi-threading. --------------------------------------------------------------------- void MTEndThread(void); This function kills the current thread. --------------------------------------------------------------------- void MTEndMultiThreading(void); This kills all known threads dead, i.e., it stops multi-threading, and cause MTStartMultiThreading() to return. --------------------------------------------------------------------- Semaphore MTCreateSema(void); This function creates and returns a unique semaphore. A semaphore of the following type: typedef unsigned int Semaphore; --------------------------------------------------------------------- unsigned MTDestroySema(Semaphore semaphore); This function destroys the specified semaphore. Trying to destroy a semaphore which is still in use, i.e. have threads blocked on it or is n possesion by a thread, is an error and will fail. The functon return 1 on success, and 0 on failure. --------------------------------------------------------------------- void MTWait(Semaphore Semaphore); This function will acquire the semaphore for the calling thread or will cause the thread to block if another thread has acquired the semaphore, until the semaphore become free. --------------------------------------------------------------------- int MTTestAndSet(Semaphore Semaphore); This is similar to MTWait(), except that the calling thread will not be block if the semaphore is not free. It return 1 if the thread is successful in acquiring the semaphore, zero if not. --------------------------------------------------------------------- void MTSignal(Semaphore Semaphore); This signals(frees) the specified semaphore. The calling thread must have possession of the semaphore before calling this function. --------------------------------------------------------------------- unsigned MTEnterCritical(void); Causes MicroThread to single-threading mode temporarily with only the calling thread executing. Zero return value indicates failure - too many nested critical sections - > MAX_CRITICAL_NESTING error. --------------------------------------------------------------------- void MTLeaveCritical(void); Causes MicroThread to revert back to multi-threading. --------------------------------------------------------------------- void MTYield(void); This causes the calling thread to yield to another thread. --------------------------------------------------------------------- void MTSetPreemptive(int bPreempt); MicroThread can be run in either pre-emptive or non pre-emptive multi-threading mode. The pre-emptive mode uses the timer interrupt to switch between threads. The non-pre-emptive mode only switches when MTYield() is called. The default mode is pre-emptive. If MTSetPreemptive() is called with the parameter bPreempt=1, then the pre-emptive mode is selected. If MTSetPreemptive() is called with the parameter bPreempt=0, then the non pre-emptive mode is selected. This function can only be called after MTInitialise() and before MTStartMultiThreading(). --------------------------------------------------------------------- Semaphore MTGetCRTLibSema(void); This function returns semaphore used in MTCRTLIB.C to serialise access to Turbo C's runtime libraries. --------------------------------------------------------------------- unsigned long MTGetClockTick(void); This returns the number of clock ticks since MTStartMultiThreading(). One second is approx. 18.2 clock ticks. --------------------------------------------------------------------- void MTSleep(unsigned long ticks); Puts the current thread to sleep for the specified number of clock ticks (at least). The length of time that the thread actually sleeps may be a few ticks more depending on however many thread are running and what they are doing. --------------------------------------------------------------------- unsigned MTCreateMailbox(char *name); MicroThread supports named mailboxes for sending messages between threads. This function creates a mailbox with the specified name, and returns a handle to the mailbox. A zero return value indicates failure. --------------------------------------------------------------------- unsigned MTDestroyMailbox(unsigned mailboxHnd); This destroys the specified mailbox. Goes without saying that destroying a mailbox which is in active use is an error. Return 1 on success and zero on failure. --------------------------------------------------------------------- unsigned MTGetMailboxHandle(char *mbxName); Retrieves the handle to the named mailbox. Returns zero if the mailbox doesn't exist. --------------------------------------------------------------------- int MTSendMsg(unsigned mailboxHnd, unsigned msgSize, void *pMsg); Sends a message(data) to the specified mailbox. The function doesn't return until a reciver has picked up the message (the rendevous method). This is also a good way of synchronizing different cooperating threads. The message is in the form of a pointer to a block of memory of size 'msgSize'. A copy of the message is made by the receiver. --------------------------------------------------------------------- int MTReceiveMsg(unsigned mailboxHnd, unsigned bufferSize, void *pBuffer); The counter part to MTSendMsg(). The calling thread will wait until there is a message in the mailbox. The memory block specified by the message is copied into the buffer pointed to by 'pBuffer'. --------------------------------------------------------------------- The following are functions in MTCRTLIB.C. They are basically semaphored-wrappers around the Turbo C runtime library functions. int MTfprintf (FILE *stream, const char *format,...); int MTprintf (const char *format,...); int MTfputs(const char *s, FILE *stream); int MTputs(char *s); int MTfputc(int c, FILE *stream); int MTputc(int c); int MTputchar(int c); FILE *MTfopen(const char *filename, const char *mode); int MTfclose(FILE *stream); int MTfeof(FILE *stream); int MTsprintf (char *buffer, const char *format,...); char *MTfgets(char *s, int n, FILE *stream); int MTfgetc(FILE *stream); int MTxyputc(int x, int y, int c); int MTxyputs(int x, int y, const char *s); int MTxyprintf (int x, int y, const char *format, ...); int MTkbhit(void); int MTgetch(void); char * MTgets(char *buf); void MTclrscr(void); int MTrandom(int num); void *MTmalloc(size_t size); void MTfree(void *block); char *MTstrcpy(char *source, char *dest); size_t MTfread(void *ptr, size_t size, size_t n, FILE *stream); size_t MTfwrite(const void *ptr, size_t size, size_t n, FILE*stream);